package com.usian.skill.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sun.prism.shader.Mask_TextureSuper_AlphaTest_Loader;
import com.usian.skill.common.CodeMsg;
import com.usian.skill.common.Result;
import com.usian.skill.mq.MQSender;
import com.usian.skill.pojo.OrderInfo;
import com.usian.skill.pojo.SkillMessage;
import com.usian.skill.pojo.SkillOrder;
import com.usian.skill.service.*;
import com.usian.skill.vo.GoodsVo;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.BlockingDeque;

/**
 * ClassName: SkillController
 * Author:   WGG
 * Date:    2022-12-2022/12/12-15:53
 * Version: 1.0
 * Description:
 */
@Controller
@RequestMapping("/skill")
public class SkillController implements InitializingBean {

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private SkillOrderService skillOrderService;

    @Autowired
    private SkillService skillService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MQSender mqSender;

    //减少对redis的访问
    private HashMap<Long, Boolean> localOverMap = new HashMap<>();


    /**
     * 初始化库存到缓存
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> allDB = goodsService.findAllDB();
        if (!CollectionUtils.isEmpty(allDB)){
            for (GoodsVo vo : allDB) {
                stringRedisTemplate.opsForValue().set("stockCount"+vo.getId(), vo.getStockCount().toString());
                localOverMap.put(vo.getId(),false);
            }
        }
    }

    @RequestMapping(value = "/{path}/skillGood", produces="text/html")
    @ResponseBody
    public Result skillGood(HttpSession session, Model model , @RequestParam("goodsId")long goodsId, @PathVariable("path") String path,@RequestParam("verifyCode") Integer verifyCode){

        //判断用户是否登录
        String userId = session.getAttribute("userId").toString();
        if (userId==null){
            return Result.error(CodeMsg.SERVER_ERROR);
        }

        boolean checkPath = skillService.checkPath(userId, goodsId, path);
        if (!checkPath){
            return Result.error(CodeMsg.REQUEST_ILLEGAL);
        }
        //检验验证码是否正确
        String code = stringRedisTemplate.opsForValue().get("VerifyCode" + userId + goodsId);
        if (Integer.parseInt(code)!=verifyCode){
            return Result.error(CodeMsg.MIAOSHA_VERIFYCODE);
        }

        //先使用本地的map进行判定，如果值为true说明库存已经没了，直接访问秒杀的结果即可，减少对redis的多次访问
        if (localOverMap.get(goodsId)) {
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }
        //查库存
        String stockCount = stringRedisTemplate.opsForValue().get("stockCount" + goodsId);

        if (Integer.parseInt(stockCount)<=0){
            localOverMap.put(goodsId,true);
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }else {

            //库存减一
            stringRedisTemplate.opsForValue().decrement("stockCount" + goodsId);
        }

        //判断用户是否重复秒杀
        SkillOrder skillOrder = skillOrderService.getOne(Wrappers.<SkillOrder>lambdaQuery()
                .eq(SkillOrder::getGoodsId, goodsId).eq(SkillOrder::getUserId, Long.parseLong(userId)));

        //如果重复秒杀
        if (skillOrder!=null){
            //库存加一
            stringRedisTemplate.opsForValue().increment("stockCount" + goodsId);
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }

        //库存大于0且没有重复秒杀 生成秒杀订单
        SkillMessage msg = new SkillMessage();
        msg.setGoodsId(goodsId);
        msg.setUserId(userId);
        mqSender.sendMiaoShaMessage(msg);
        //告知用户正在排队
        return Result.success(0);

    }

    /**
     * orderId:成功
     * -1：秒杀失败
     * 0：排队中
     * @param model
     * @param session
     * @param goodsId
     * @return
     */
    @RequestMapping(value = "/result",method = RequestMethod.GET)
    @ResponseBody
    public Result<Long> miaoshaResult(Model model, HttpSession session, @RequestParam("goodsId")long goodsId){
        //判断用户是否登录
        String userId = session.getAttribute("userId").toString();
        if (userId==null){
            return Result.error(CodeMsg.SERVER_ERROR);
        }
        long result = skillService.getSkillResult(userId,goodsId);
        return Result.success(result);
    }

    @RequestMapping(value = "/path",method = RequestMethod.GET)
    @ResponseBody
    public Result<String> getSkillPath(HttpSession session,@RequestParam("goodsId")long goodsId){
        //判断用户是否登录
        String userId = session.getAttribute("userId").toString();
        if (userId==null){
            return Result.error(CodeMsg.SERVER_ERROR);
        }
        //调用创建随机数的方法
        String path = skillService.createMiaoShaPath(userId, goodsId);
        return Result.success(path);
    }


    @RequestMapping(value="/verifyCode", method=RequestMethod.GET)
    @ResponseBody
    public Result<String> getMiaoshaVerifyCod(HttpServletResponse response, HttpSession session,
                                              @RequestParam("goodsId")long goodsId) {
        String userId =(String)session.getAttribute("userId");
        if(userId == null) {
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        try {
            BufferedImage image  = skillService.createVerifyCode(userId, goodsId);
            OutputStream out = response.getOutputStream();
            ImageIO.write(image, "JPEG", out);
            out.flush();
            out.close();
            return null;
        }catch(Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.MIAOSHA_FAIL);
        }
    }
}
